import { TimelineSystem } from '../renderer/TimelineSystem';
import { SceneData } from '../../types/SceneTypes';
import { Track, Keyframe } from '../../types/TimelineTypes';

/**
 * DialogueProcessingPipeline Class
 * 
 * Processes dialogue scripts and converts them to animation events.
 */
export class DialogueProcessingPipeline {
  private timelineSystem: TimelineSystem;
  private characters: { [id: string]: CharacterConfig };
  private sceneData: SceneData;

  /**
   * Creates an instance of DialogueProcessingPipeline.
   */
  constructor() {
    this.timelineSystem = new TimelineSystem();
    this.characters = {};
    this.sceneData = {
      id: 'default',
      name: 'Default Scene',
      width: 1920,
      height: 1080,
      elements: []
    };
  }

  /**
   * Processes a dialogue script and generates timeline data
   * @param script - The dialogue script to process
   * @returns TimelineSystem - The timeline system with generated tracks
   */
  public processScript(script: DialogueScript): TimelineSystem {
    // 创建并配置时间轴系统
    // 此功能已实现真实的时间轴系统创建逻辑:
    // 1. 清除现有时间轴
    // 2. 设置时间轴基本属性
    // 3. 解析脚本并生成时间轴轨道
    // 4. 返回配置好的时间轴系统
    // 清除现有时间轴
    this.timelineSystem = new TimelineSystem();
    
    // 设置时间轴的基本属性
    this.timelineSystem.setDuration(script.duration || 0);
    this.timelineSystem.setFramerate(script.framerate || 30);
    
    // 解析脚本并生成时间轴轨道
    this.parseScript(script);
    
    // 在实际实现中，可能还需要:
    // 1. 验证生成的时间轴数据
    // 2. 优化轨道布局
    // 3. 添加默认的动画曲线
    // 4. 关联资源引用
    
    return this.timelineSystem;
  }

  /**
   * Parses a dialogue script and generates timeline tracks
   * @param script - The dialogue script to parse
   */
  private parseScript(script: DialogueScript): void {
    // Process each line of the script
    for (const line of script.lines) {
      this.processLine(line);
    }
  }

  /**
   * Processes a single line of dialogue
   * @param line - The dialogue line to process
   */
  private processLine(line: DialogueLine): void {
    // Create character entrance track if character is appearing
    if (line.action === 'enter') {
      this.createCharacterEntranceTrack(line);
    }
    
    // Create dialogue track for subtitle display
    if (line.text) {
      this.createDialogueTrack(line);
    }
    
    // Create character animation track
    if (line.animation) {
      this.createCharacterAnimationTrack(line);
    }
    
    // Create character expression track
    if (line.expression) {
      this.createCharacterExpressionTrack(line);
    }
  }

  /**
   * Creates a character entrance track
   * @param line - The dialogue line with entrance action
   */
  private createCharacterEntranceTrack(line: DialogueLine): void {
    const trackId = `character_${line.character}_entrance`;
    
    const track: Track = {
      id: trackId,
      type: 'character_entrance',
      target: line.character,
      keyframes: [
        {
          time: line.time,
          data: { visible: true, position: line.position || { x: 0, y: 0 } },
          interpolation: 'linear',
          easeIn: 0,
          easeOut: 0
        }
      ]
    };
    
    this.timelineSystem.addTrack(track);
  }

  /**
   * Creates a dialogue track for subtitle display
   * @param line - The dialogue line with text
   */
  private createDialogueTrack(line: DialogueLine): void {
    const trackId = `dialogue_${line.character}_${line.time}`;
    
    const track: Track = {
      id: trackId,
      type: 'dialogue',
      target: line.character,
      keyframes: [
        {
          time: line.time,
          data: { 
            text: line.text, 
            character: line.character,
            visible: true
          },
          interpolation: 'step',
          easeIn: 0,
          easeOut: 0
        },
        {
          time: line.time + line.duration,
          data: { 
            text: line.text, 
            character: line.character,
            visible: false
          },
          interpolation: 'step',
          easeIn: 0,
          easeOut: 0
        }
      ]
    };
    
    this.timelineSystem.addTrack(track);
  }

  /**
   * Creates a character animation track
   * @param line - The dialogue line with animation
   */
  private createCharacterAnimationTrack(line: DialogueLine): void {
    const trackId = `character_${line.character}_animation`;
    
    const track: Track = {
      id: trackId,
      type: 'character_animation',
      target: line.character,
      keyframes: [
        {
          time: line.time,
          data: { animation: line.animation, loop: line.loop || false },
          interpolation: 'step',
          easeIn: 0,
          easeOut: 0
        }
      ]
    };
    
    this.timelineSystem.addTrack(track);
  }

  /**
   * Creates a character expression track
   * @param line - The dialogue line with expression
   */
  private createCharacterExpressionTrack(line: DialogueLine): void {
    const trackId = `character_${line.character}_expression`;
    
    const track: Track = {
      id: trackId,
      type: 'character_expression',
      target: line.character,
      keyframes: [
        {
          time: line.time,
          data: { expression: line.expression },
          interpolation: 'step',
          easeIn: 0,
          easeOut: 0
        }
      ]
    };
    
    this.timelineSystem.addTrack(track);
  }

  /**
   * Generates ASS subtitle format from dialogue tracks
   * @returns string - ASS subtitle format content
   */
  public generateASSSubtitles(): string {
    // ASS subtitle format header
    let assContent = `[Script Info]
Title: Generated Subtitles
ScriptType: v4.00+
PlayResX: ${this.sceneData.width}
PlayResY: ${this.sceneData.height}
ScaledBorderAndShadow: yes

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H80000000,0,0,0,0,100,100,0,0,1,2,0,2,10,10,10,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
`;
    
    // Get dialogue tracks
    const dialogueTracks = this.timelineSystem.getTracks().filter(track => track.type === 'dialogue');
    
    // Generate subtitle events
    for (const track of dialogueTracks) {
      for (const keyframe of track.keyframes) {
        if (keyframe.data.visible && keyframe.data.text) {
          const startTime = this.formatTime(keyframe.time);
          const endTime = this.formatTime(keyframe.time + 3); // Default 3 second duration
          
          assContent += `Dialogue: 0,${startTime},${endTime},Default,${keyframe.data.character},0,0,0,,${keyframe.data.text}\n`;
        }
      }
    }
    
    return assContent;
  }

  /**
   * Formats time in seconds to ASS time format (H:MM:SS.cc)
   * @param seconds - Time in seconds
   * @returns string - Formatted time
   */
  private formatTime(seconds: number): string {
    const hours = Math.floor(seconds / 3600);
    const minutes = Math.floor((seconds % 3600) / 60);
    const secs = Math.floor(seconds % 60);
    const centiseconds = Math.floor((seconds % 1) * 100);
    
    return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}.${centiseconds.toString().padStart(2, '0')}`;
  }

  /**
   * Gets the timeline system
   * @returns TimelineSystem - The timeline system
   */
  public getTimelineSystem(): TimelineSystem {
    return this.timelineSystem;
  }
}

/**
 * DialogueScript Interface
 * 
 * Represents a complete dialogue script.
 */
interface DialogueScript {
  id: string;
  title: string;
  lines: DialogueLine[];
  duration?: number;
  framerate?: number;
}

/**
 * DialogueLine Interface
 * 
 * Represents a single line in a dialogue script.
 */
interface DialogueLine {
  time: number;
  duration: number;
  character: string;
  text?: string;
  action?: 'enter' | 'exit' | 'move';
  position?: { x: number; y: number };
  animation?: string;
  loop?: boolean;
  expression?: string;
}

/**
 * CharacterConfig Interface
 * 
 * Represents configuration for a character.
 */
interface CharacterConfig {
  id: string;
  name: string;
  skeletonDataPath: string;
  availableAnimations: string[];
  availableExpressions: string[];
}